package org.front.client.widget.distributeurwidget;

import java.util.ArrayList;
import java.util.List;

import org.front.client.service.DistributeurService;
import org.front.client.service.DistributeurServiceAsync;
import org.front.client.utils.DistributeurUtils;
import org.front.client.widget.distributeurwidget.event.DistributeurWidgetEvent;
import org.front.client.widget.distributeurwidget.event.DistributeurWidgetHandler;
import org.front.client.widget.mainwidget.i18n.images.MainWidgetImages;
import org.front.shared.data.Compartiment;
import org.front.shared.data.Distributeur;
import org.front.shared.data.Produit;
import org.front.shared.wrap.ModifierCompartimentRequest;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.shared.EventBus;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.resources.client.ClientBundle;
import com.google.gwt.resources.client.ImageResource;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.uibinder.client.UiTemplate;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.Grid;
import com.google.gwt.user.client.ui.HorizontalPanel;
import com.google.gwt.user.client.ui.Image;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.ListBox;
import com.google.gwt.user.client.ui.VerticalPanel;
import com.google.gwt.user.client.ui.Widget;

public class DistributeurWidget extends Composite implements DistributeurWidgetHandler {

	private final DistributeurServiceAsync distributeurService = GWT.create(DistributeurService.class);

	Grid gridChoixCompartiment;
	Grid gridDistributeur;
	Grid gridPiece;

	Distributeur distributeur;

	/** UIBinder bindings */
	@UiField
	FlowPanel rootPanel;
	@UiField
	FlowPanel loading;
	
	@UiField
	FlowPanel global;

	@UiField
	FlowPanel distributeurPanel;
	@UiField
	Image imageResultat;

	@UiField
	FlowPanel choixCompartimentPanel;
	@UiField
	Button button1;
	@UiField
	Button button2;
	@UiField
	Button button3;
	@UiField
	Button button4;
	@UiField
	Button button5;
	@UiField
	Button button6;
	@UiField
	Button button7;
	@UiField
	Button button8;
	@UiField
	Button button9;
	@UiField
	Button button0;
	@UiField
	Button buttonAnnuler;
	@UiField
	Button buttonValider;
	@UiField
	Label choixValue;
	@UiField
	Label messageInformation;

	/** Panel payerBoissonPanel */
	@UiField
	FlowPanel payerBoissonPanel;
	@UiField
	Button dixCentime;
	@UiField
	Button vingtCentime;
	@UiField
	Button cinquanteCentime;
	@UiField
	Button unEuro;
	@UiField
	Button deuxEuro;
	@UiField
	Label montantAchatCourantValue;
	
	/** event bus on which to commit */
	private final EventBus eventBus;
	
	/** Handlers the widget registers */
	private final List<HandlerRegistration> handlersRegistration;

	/**
	 * Client Bundle resources for this widget
	 */
	public interface Resources extends ClientBundle {

		/** Instance */
		public Resources INSTANCE = GWT.create(Resources.class);

		/**
		 * @return Css
		 */
		@Source("DistributeurWidget.css")
		DistributeurWidgetCssResources css();

		/**
		 * @return Images du widget
		 */
		MainWidgetImages images();
	}

	/**
	 * Declare UIBinder for this widget
	 */
	@UiTemplate("DistributeurWidget.ui.xml")
	interface MainWidgetUiBinder extends UiBinder<Widget, DistributeurWidget> {
	}

	/** UIBinder for building interface */
	private final MainWidgetUiBinder uiBinder;

	public DistributeurWidget(EventBus eventBus) {
		
		this.eventBus = eventBus;

		// registration of handlers
		this.handlersRegistration = new ArrayList<HandlerRegistration>();
		
		// create UI
		this.uiBinder = GWT.create(MainWidgetUiBinder.class);
		initWidget(this.uiBinder.createAndBindUi(this));
		Resources.INSTANCE.css().ensureInjected();
		rootPanel.setStyleName("main");
	}

	public void initialiserData() {
		this.loading.setVisible(true);
		initDistributeur();
	}

	private void afficherChoixCompartimentPanel() {

		if (gridChoixCompartiment != null) {
			choixCompartimentPanel.remove(gridChoixCompartiment);
		}

		gridChoixCompartiment = new Grid(4, 3);
		gridChoixCompartiment.setWidget(0, 0, button1);
		gridChoixCompartiment.setWidget(0, 1, button2);
		gridChoixCompartiment.setWidget(0, 2, button3);
		gridChoixCompartiment.setWidget(1, 0, button4);
		gridChoixCompartiment.setWidget(1, 1, button5);
		gridChoixCompartiment.setWidget(1, 2, button6);
		gridChoixCompartiment.setWidget(2, 0, button7);
		gridChoixCompartiment.setWidget(2, 1, button8);
		gridChoixCompartiment.setWidget(2, 2, button9);
		gridChoixCompartiment.setWidget(3, 0, button0);
		gridChoixCompartiment.setWidget(3, 1, buttonAnnuler);
		gridChoixCompartiment.setWidget(3, 2, buttonValider);

		choixCompartimentPanel.add(gridChoixCompartiment);
	}

	
	private void acheterProduit(Compartiment compartiment) {

		String ligne = compartiment.getNumero().substring(0, 1);
		String colonne = compartiment.getNumero().substring(1, 2);
		gridDistributeur.setWidget(Integer.valueOf(ligne) - 1, Integer.valueOf(colonne), loading);
		loading.setVisible(true);

		distributeurService.acheterProduit(compartiment, new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void result) {
				GWT.log("Success : acheterProduit");
				initialiserData();
			}

			@Override
			public void onFailure(Throwable caught) {
				GWT.log("Failure : acheterProduit");
			}
		});
	}

	private void afficherPayerBoissonPanel() {

		if (gridPiece != null) {
			payerBoissonPanel.remove(gridPiece);
		}

		gridPiece = new Grid(5, 1);
		gridPiece.setWidget(0, 0, dixCentime);
		gridPiece.setWidget(1, 0, vingtCentime);
		gridPiece.setWidget(2, 0, cinquanteCentime);
		gridPiece.setWidget(3, 0, unEuro);
		gridPiece.setWidget(4, 0, deuxEuro);

		payerBoissonPanel.add(gridPiece);
	}

	private void initDistributeur() {
		distributeurService.getDistributeur(new AsyncCallback<Distributeur>() {

			@Override
			public void onSuccess(Distributeur result) {
				GWT.log("Success : getDistributeur");
				populateData(result);
			}

			@Override
			public void onFailure(Throwable caught) {
				GWT.log("Failure : getDistributeur " + caught);
			}
		});
	}

	/**
	 * Recuperation du distributeur et appel a l'affichage des blocs
	 * 
	 * @param result
	 */
	private void populateData(Distributeur result) {
		distributeur = result;
		afficherDistributeurPanel();
		afficherPayerBoissonPanel();
		afficherChoixCompartimentPanel();
		this.loading.setVisible(false);
		this.global.setVisible(true);
	}

	/**
	 * Affiche le distributeur
	 */
	private void afficherDistributeurPanel() {

		if (gridDistributeur != null) {
			distributeurPanel.remove(gridDistributeur);
		}

		gridDistributeur = new Grid(distributeur.getNombreLigne(), distributeur.getNombreColonne());

		for (int indiceLigne = 0; indiceLigne < distributeur.getNombreLigne(); indiceLigne++) {

			for (int indiceColonne = 0; indiceColonne < distributeur.getNombreColonne(); indiceColonne++) {

				VerticalPanel compartimentPanel = new VerticalPanel();

				FlowPanel panelImage = new FlowPanel();
				panelImage.setStylePrimaryName(Resources.INSTANCE.css().DistributeurWidgetCenter());

				final String keyCompartiment = String.valueOf(indiceLigne + 1) + String.valueOf(indiceColonne);

				final Compartiment compartiment = distributeur.getMapCompartiment().get(keyCompartiment);
				if (compartiment != null) {
					Produit produit = compartiment.getProduit();
					ImageResource imageResource = DistributeurUtils.getImageProduit(produit.getCode());
					if (imageResource == null) {
						Label labelProduit = new Label(produit.getDescription());
						panelImage.add(labelProduit);
						labelProduit.setHeight("30px");
						labelProduit.setWidth("45px");
					} else {
						Image image = new Image(imageResource);
						image.setHeight("30px");
						image.setAltText(produit.getDescription());
						panelImage.add(image);
					}
				}

				compartimentPanel.add(panelImage);

				Label numeroCompartiment = new Label(keyCompartiment);
				numeroCompartiment.setStylePrimaryName(Resources.INSTANCE.css().DistributeurWidgetNumeroCompartiment());
				compartimentPanel.add(numeroCompartiment);

				if (compartiment != null) {
					Produit produit = compartiment.getProduit();
					Label prix = new Label("Prix : " + String.valueOf(produit.getPrix()));
					prix.setStylePrimaryName(Resources.INSTANCE.css().DistributeurWidgetPrix());
					compartimentPanel.add(prix);

					Label quantite = new Label("Quantite : " + String.valueOf(compartiment.getQuantite()));
					quantite.setStylePrimaryName(Resources.INSTANCE.css().DistributeurWidgetQuantite());
					compartimentPanel.add(quantite);
				}

				FlowPanel modificationPanel = new FlowPanel();
				Button buttonModifier = new Button("Modifier");
				buttonModifier.addClickHandler(new ClickHandler() {

					@Override
					public void onClick(ClickEvent event) {

						final DialogBox dialogBox = new DialogBox();
						dialogBox.setText("Modification du compartiment " + keyCompartiment);

						FlowPanel panelDialog = new FlowPanel();

						FlowPanel panelListProduit = new FlowPanel();
						HorizontalPanel produits = new HorizontalPanel();
						Label labelProduits = new Label("Produit ");
						final ListBox listBoxProduit = new ListBox(false);
						for (Produit produit : distributeur.getListProduits()) {
							listBoxProduit.addItem(produit.getDescription(), produit.getCode());
						}

						produits.add(labelProduits);
						produits.add(listBoxProduit);
						panelListProduit.add(produits);

						if (compartiment == null) {
							panelDialog.add(panelListProduit);
						} else {
							panelDialog.add(new Label("Produit : " + compartiment.getProduit().getDescription()));
						}

						FlowPanel panelListQuantite = new FlowPanel();
						HorizontalPanel quantite = new HorizontalPanel();
						Label labelQuantite = new Label("Quantite ");

						final ListBox listBoxQuantite = new ListBox(false);
						for (int i = 1; i < 11; i++) {
							listBoxQuantite.addItem(String.valueOf(i));
						}

						quantite.add(labelQuantite);
						quantite.add(listBoxQuantite);
						panelListQuantite.add(quantite);

						panelDialog.add(panelListQuantite);

						FlowPanel panelButton = new FlowPanel();
						Button closeButton = new Button("Annuler", new ClickHandler() {
							@Override
							public void onClick(ClickEvent event) {
								dialogBox.hide();
							}
						});
						panelButton.add(closeButton);

						Button validerButton = new Button("Valider", new ClickHandler() {
							@Override
							public void onClick(ClickEvent event) {

								ModifierCompartimentRequest request = new ModifierCompartimentRequest();

								if (compartiment == null) {
									Compartiment compartimentToUpdate = new Compartiment();
									compartimentToUpdate.setNumero(keyCompartiment);
									request.setCompartiment(compartimentToUpdate);

									Produit produit = new Produit();
									produit.setCode(listBoxProduit.getValue(listBoxProduit.getSelectedIndex()));
									request.setProduit(produit);

									request.setQuantite(Integer.valueOf(listBoxQuantite.getValue(listBoxQuantite.getSelectedIndex())));
									request.setCreation(true);
								} else {
									request.setCompartiment(compartiment);
									request.setProduit(compartiment.getProduit());
									request.setQuantite(Integer.valueOf(listBoxQuantite.getValue(listBoxQuantite.getSelectedIndex())));
									request.setCreation(false);
								}

								modifierCompartiment(request);
								dialogBox.hide();
							}
						});
						panelButton.add(validerButton);
						panelDialog.add(panelButton);

						dialogBox.setWidget(panelDialog);
						dialogBox.setGlassEnabled(true);
						dialogBox.setAnimationEnabled(true);
						dialogBox.center();
						dialogBox.show();

					}
				});
				modificationPanel.add(buttonModifier);
				compartimentPanel.add(modificationPanel);
				gridDistributeur.setWidget(indiceLigne, indiceColonne, compartimentPanel);
			}
		}

		gridDistributeur.setBorderWidth(0);
		gridDistributeur.setCellPadding(15);

		distributeurPanel.add(gridDistributeur);
	}

	public void modifierCompartiment(ModifierCompartimentRequest request) {

		String ligne = request.getCompartiment().getNumero().substring(0, 1);
		String colonne = request.getCompartiment().getNumero().substring(1, 2);
		gridDistributeur.setWidget(Integer.valueOf(ligne) - 1, Integer.valueOf(colonne), loading);
		loading.setVisible(true);

		distributeurService.modifierCompartiment(request, new AsyncCallback<Void>() {

			@Override
			public void onSuccess(Void result) {
				GWT.log("Success : modifierCompartiment");
				initialiserData();
			}

			@Override
			public void onFailure(Throwable caught) {
				GWT.log("Failure : modifierCompartiment");
			}
		});
	}

	private void updateAchatCourant() {
		this.montantAchatCourantValue.setText(String.valueOf(distributeur.getAchatCourant()));
	}

	@UiHandler("button1")
	protected void onButton1(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "1");
	}

	@UiHandler("button2")
	protected void onButton2(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "2");
	}

	@UiHandler("button3")
	protected void onButton3(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "3");
	}

	@UiHandler("button4")
	protected void onButton4(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "4");
	}

	@UiHandler("button5")
	protected void onButton5(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "5");
	}

	@UiHandler("button6")
	protected void onButton6(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "6");
	}

	@UiHandler("button7")
	protected void onButton7(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "7");
	}

	@UiHandler("button8")
	protected void onButton8(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "8");
	}

	@UiHandler("button9")
	protected void onButton9(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "9");
	}

	@UiHandler("button0")
	protected void onButton0(ClickEvent event) {
		choixValue.setText(choixValue.getText() + "0");
	}

	@UiHandler("buttonAnnuler")
	protected void onButtonAnnuler(ClickEvent event) {
		choixValue.setText("");
		if (distributeur.getAchatCourant() != 0) {
			distributeur.setAchatCourant(0.0);
			updateAchatCourant();
			messageInformation.setText("Recuperez votre monaie");
		}
	}

	@UiHandler("buttonValider")
	protected void onButtonValider(ClickEvent event) {

		if (choixValue.getText().length() < 2) {
			messageInformation.setText("Veuiller choisir deux chiffres");
			choixValue.setText("");
			return;
		}

		if (distributeur.getMapCompartiment().get(choixValue.getText()) == null) {
			messageInformation.setText("il n'y a pas de produit sur le code " + choixValue.getText());
			choixValue.setText("");
			return;
		}

		Produit produit = distributeur.getMapCompartiment().get(choixValue.getText()).getProduit();
		messageInformation.setText("");

		if (distributeur.getAchatCourant() < produit.getPrix()) {
			messageInformation.setText("Veuillez ajouter " + String.valueOf(produit.getPrix() - distributeur.getAchatCourant()));
			return;
		}

		messageInformation.setText("Veuillez recuperer votre " + produit.getDescription());

		if (distributeur.getAchatCourant() > produit.getPrix()) {
			messageInformation.setText(messageInformation.getText() + ". N'oubliez pas votre monnaie (" + String.valueOf(distributeur.getAchatCourant() - produit.getPrix()) + ")");
		}

		imageResultat.setResource(Resources.INSTANCE.images().loading());
		acheterProduit(distributeur.getMapCompartiment().get(choixValue.getText()));

		distributeur.setAchatCourant(0.0);
		updateAchatCourant();
		choixValue.setText("");
		if (DistributeurUtils.getImageProduit(produit.getCode()) != null) {
			imageResultat.setResource(DistributeurUtils.getImageProduit(produit.getCode()));
		}
	}

	@UiHandler("dixCentime")
	protected void onButtonDixCentime(ClickEvent event) {
		distributeur.addAchatCourant(0.1);
		updateAchatCourant();
	}

	@UiHandler("vingtCentime")
	protected void onButtonVingtCentime(ClickEvent event) {
		distributeur.addAchatCourant(0.2);
		updateAchatCourant();
	}

	@UiHandler("cinquanteCentime")
	protected void onButtonCinquanteCentime(ClickEvent event) {
		distributeur.addAchatCourant(0.5);
		updateAchatCourant();
	}

	@UiHandler("unEuro")
	protected void onButtonUnEuro(ClickEvent event) {
		distributeur.addAchatCourant(1.0);
		updateAchatCourant();
	}

	@UiHandler("deuxEuro")
	protected void onButtonDeuxEuro(ClickEvent event) {
		distributeur.addAchatCourant(2.0);
		updateAchatCourant();
	}

	
	@Override
	protected void onLoad() {
		
		super.onLoad();
		bind();
	}
	
	@Override
	protected void onUnload() {
		super.onUnload();
		unbind();
	}
	
	/**
	 * Bind handler
	 */
	protected void bind() {
		this.handlersRegistration.add(this.eventBus.addHandler(DistributeurWidgetEvent.TYPE, this));
	}

	/**
	 * Unbing handler
	 */
	protected void unbind() {
		// remove handlers registration
		for (final HandlerRegistration hr : this.handlersRegistration) {
			hr.removeHandler();
		}
		this.handlersRegistration.clear();
	}

	@Override
	public void onMainWidget(DistributeurWidgetEvent event) {
		// TODO Auto-generated method stub
		
	}
}
